<template>
  <el-dialog
    v-model="visible"
    title="摄像头识别"
    width="900px"
    :before-close="handleClose"
    destroy-on-close
  >
    <div class="camera-modal">
      <!-- 用户信息展示 -->
      <div class="user-info-section">
        <h4>👤 当前用户信息</h4>
        <div v-if="isUserLoggedIn" class="user-info-card">
          <div class="user-avatar">
            <el-avatar 
              :size="50" 
              :src="currentUser.avatar" 
              :icon="User"
            />
          </div>
          <div class="user-details">
            <div class="user-name">
              <el-icon><User /></el-icon>
              <span>{{ currentUser.nickname || '未设置昵称' }}</span>
            </div>
            <div class="user-id">
              <span class="label">用户ID:</span>
              <el-tag type="primary" size="small">{{ currentUser.id }}</el-tag>
            </div>
          </div>
        </div>
        <div v-else class="user-info-empty">
          <el-alert
            title="用户未登录"
            description="请先登录系统后再进行人脸识别操作"
            type="warning"
            :closable="false"
            show-icon
          />
        </div>
      </div>

      <!-- 配置选择 -->
      <div class="config-section">
        <h4>⚙️ 人脸配置</h4>
        <el-form :model="recognizeForm" label-width="100px">
          <el-form-item label="配置选择" required>
            <el-select
              v-model="recognizeForm.configId"
              placeholder="请选择人脸识别配置"
              style="width: 100%"
              :loading="configLoading"
            >
              <el-option
                v-for="config in configList"
                :key="config.id"
                :label="config.name"
                :value="config.id"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="用户组ID">
            <el-input
              v-model="recognizeForm.groupId"
              placeholder="可选，用于分组管理"
              clearable
            />
          </el-form-item>
        </el-form>
      </div>

      <!-- 摄像头区域 -->
      <div class="camera-section">
        <h4>📷 摄像头拍照</h4>
        <div class="camera-container">
          <div class="camera-preview">
            <!-- 摄像头状态指示器 -->
            <div :class="['camera-status', cameraActive ? 'active' : 'inactive']">
              <div class="camera-status-dot"></div>
              {{ cameraActive ? '摄像头已开启 - 请保持人脸在画面中央' : '摄像头已关闭' }}
            </div>
            
            <video
              ref="videoRef"
              v-show="cameraActive"
              autoplay
              playsinline
              class="camera-video"
            ></video>
            <canvas
              ref="canvasRef"
              v-show="false"
              class="camera-canvas"
            ></canvas>
            
            <!-- 拍摄的照片预览 -->
            <div v-if="capturedImageUrl && !cameraActive" class="captured-preview">
              <img :src="capturedImageUrl" alt="拍摄的照片" class="captured-image" />
              <div class="captured-overlay">
                <el-button type="primary" size="small" @click="startCamera">
                  <el-icon><VideoCamera /></el-icon>
                  重新拍照
                </el-button>
              </div>
            </div>
            
            <div v-if="!cameraActive && !capturedImageUrl" class="camera-placeholder">
              <el-icon size="48"><Camera /></el-icon>
              <p>点击开启摄像头开始拍照</p>
              <p class="placeholder-tip">请确保光线充足，人脸清晰可见</p>
            </div>
          </div>
          
          <div class="camera-controls">
            <el-button
              v-if="!cameraActive"
              type="primary"
              @click="startCamera"
              :loading="cameraLoading"
            >
              <el-icon><VideoCamera /></el-icon>
              开启摄像头
            </el-button>
            <template v-else>
              <el-button
                type="success"
                @click="capturePhoto"
                :disabled="!cameraActive"
              >
                <el-icon><Camera /></el-icon>
                拍照
              </el-button>
              <el-button
                type="danger"
                @click="stopCamera"
              >
                <el-icon><Close /></el-icon>
                关闭摄像头
              </el-button>
            </template>
          </div>
        </div>
      </div>

      <!-- 识别操作 -->
      <div class="action-section">
        <h4>🎯 识别操作</h4>
        <div class="action-buttons">
          <el-button
            type="primary"
            @click="() => handleRecognize('register')"
            :disabled="!canRecognize"
            :loading="recognizeLoading"
          >
            <el-icon><UserFilled /></el-icon>
            人脸注册
          </el-button>
          <el-button
            type="success"
            @click="() => handleRecognize('search')"
            :disabled="!canRecognize"
            :loading="recognizeLoading"
          >
            <el-icon><Search /></el-icon>
            人脸搜索
          </el-button>
          <el-button
            type="warning"
            @click="() => handleRecognize('detect')"
            :disabled="!canRecognize"
            :loading="recognizeLoading"
          >
            <el-icon><View /></el-icon>
            人脸检测
          </el-button>
        </div>
      </div>

      <!-- 识别结果 -->
      <div class="result-section" v-if="recognizeResult">
        <h4>📊 识别结果</h4>
        <div class="result-content">
          <div v-if="recognizeResult.success" class="result-success">
            <el-alert
              title="识别成功"
              type="success"
              :closable="false"
              show-icon
            >
              <template #default>
                <div class="result-details">
                  <div v-if="recognizeResult.data.userId" class="result-item">
                    <span class="result-label">用户ID:</span>
                    <el-tag type="primary">{{ recognizeResult.data.userId }}</el-tag>
                  </div>
                  <div v-if="recognizeResult.data.similarity" class="result-item">
                    <span class="result-label">相似度:</span>
                    <el-tag :type="getSimilarityType(recognizeResult.data.similarity)">
                      {{ (recognizeResult.data.similarity * 100).toFixed(2) }}%
                    </el-tag>
                  </div>
                  <div v-if="recognizeResult.data.faceCount" class="result-item">
                    <span class="result-label">人脸数量:</span>
                    <el-tag type="info">{{ recognizeResult.data.faceCount }}</el-tag>
                  </div>
                  <div v-if="recognizeResult.data.processTime" class="result-item">
                    <span class="result-label">处理时间:</span>
                    <el-tag type="info">{{ recognizeResult.data.processTime }}ms</el-tag>
                  </div>
                </div>
              </template>
            </el-alert>
          </div>
          <div v-else class="result-error">
            <el-alert
              title="识别失败"
              :description="recognizeResult.message"
              type="error"
              :closable="false"
              show-icon
            />
          </div>
        </div>
      </div>
    </div>

    <template #footer>
      <span class="dialog-footer">
        <el-button @click="handleClose">关闭</el-button>
        <el-button type="primary" @click="clearResult" v-if="recognizeResult">
          清除结果
        </el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, computed, watch, onUnmounted } from 'vue'
import { ElMessage } from 'element-plus'
import { User, VideoCamera, Camera, Close, UserFilled, Search, View } from '@element-plus/icons-vue'
import { useUserStore } from '@/store/modules/user'
import * as FaceApi from '@/api/infra/face'

interface Props {
  modelValue: boolean
  configList: any[]
  configLoading: boolean
}

interface Emits {
  (e: 'update:modelValue', value: boolean): void
  (e: 'success', result: any): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

const userStore = useUserStore()
const videoRef = ref<HTMLVideoElement>()
const canvasRef = ref<HTMLCanvasElement>()

const visible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})

// 用户信息
const currentUser = computed(() => userStore.getUser)
const isUserLoggedIn = computed(() => !!currentUser.value?.id)

// 表单数据
const recognizeForm = ref({
  configId: null,
  userId: computed(() => currentUser.value?.id),
  groupId: ''
})

// 摄像头状态
const cameraActive = ref(false)
const cameraLoading = ref(false)
const capturedImageUrl = ref('')
const capturedImageData = ref('')
let mediaStream: MediaStream | null = null

// 识别状态
const recognizeLoading = ref(false)
const recognizeResult = ref(null)

// 计算属性
const canRecognize = computed(() => {
  return isUserLoggedIn.value && 
         recognizeForm.value.configId && 
         capturedImageData.value
})

// 开启摄像头
const startCamera = async () => {
  cameraLoading.value = true
  try {
    mediaStream = await navigator.mediaDevices.getUserMedia({
      video: { width: 640, height: 480 }
    })
    
    if (videoRef.value) {
      videoRef.value.srcObject = mediaStream
      cameraActive.value = true
      // 清除之前拍摄的照片
      capturedImageUrl.value = ''
      capturedImageData.value = ''
      recognizeResult.value = null
    }
  } catch (error: any) {
    ElMessage.error('无法访问摄像头: ' + error.message)
  } finally {
    cameraLoading.value = false
  }
}

// 关闭摄像头
const stopCamera = () => {
  if (mediaStream) {
    mediaStream.getTracks().forEach(track => track.stop())
    mediaStream = null
  }
  cameraActive.value = false
}

// 拍照
const capturePhoto = () => {
  if (!videoRef.value || !canvasRef.value) return
  
  const video = videoRef.value
  const canvas = canvasRef.value
  const context = canvas.getContext('2d')
  
  if (!context) return
  
  // 设置画布尺寸
  canvas.width = video.videoWidth
  canvas.height = video.videoHeight
  
  // 绘制视频帧到画布
  context.drawImage(video, 0, 0)
  
  // 获取图片数据
  capturedImageUrl.value = canvas.toDataURL('image/jpeg', 0.8)
  capturedImageData.value = capturedImageUrl.value.split(',')[1] // 获取base64数据部分
  
  // 关闭摄像头
  stopCamera()
  
  // 清除之前的识别结果
  recognizeResult.value = null
  
  ElMessage.success('拍照成功')
}

// 识别操作
const handleRecognize = async (type: 'register' | 'search' | 'detect') => {
  if (!canRecognize.value) {
    ElMessage.warning('请先登录并选择配置，然后拍摄照片')
    return
  }
  
  recognizeLoading.value = true
  recognizeResult.value = null
  
  try {
    const params = {
      configId: recognizeForm.value.configId!,
      userId: recognizeForm.value.userId!,
      groupId: recognizeForm.value.groupId || undefined,
      image: capturedImageData.value
    }
    
    let result
    switch (type) {
      case 'register':
        result = await FaceApi.registerFaceBase64(params)
        break
      case 'search':
        result = await FaceApi.searchFaceBase64(params)
        break
      case 'detect':
        result = await FaceApi.detectFaceBase64(params)
        break
    }
    
    recognizeResult.value = {
      success: true,
      data: result,
      type
    }
    
    ElMessage.success(`人脸${type === 'register' ? '注册' : type === 'search' ? '搜索' : '检测'}成功`)
    emit('success', result)
    
  } catch (error: any) {
    recognizeResult.value = {
      success: false,
      message: error.message || '识别失败',
      type
    }
    ElMessage.error(error.message || '识别失败')
  } finally {
    recognizeLoading.value = false
  }
}

// 获取相似度标签类型
const getSimilarityType = (similarity: number) => {
  if (similarity >= 0.9) return 'success'
  if (similarity >= 0.7) return 'warning'
  return 'danger'
}

// 清除结果
const clearResult = () => {
  recognizeResult.value = null
}

// 关闭弹窗
const handleClose = () => {
  visible.value = false
  // 清理摄像头
  stopCamera()
  // 清理数据
  recognizeForm.value.configId = null
  recognizeForm.value.groupId = ''
  capturedImageUrl.value = ''
  capturedImageData.value = ''
  recognizeResult.value = null
}

// 监听弹窗打开，重置表单
watch(visible, (newVal) => {
  if (newVal) {
    recognizeForm.value.configId = null
    recognizeForm.value.groupId = ''
    capturedImageUrl.value = ''
    capturedImageData.value = ''
    recognizeResult.value = null
  } else {
    // 弹窗关闭时确保摄像头被关闭
    stopCamera()
  }
})

// 组件卸载时清理摄像头
onUnmounted(() => {
  stopCamera()
})
</script>

<style scoped>
.camera-modal {
  padding: 20px 0;
}

.user-info-section,
.config-section,
.camera-section,
.action-section,
.result-section {
  margin-bottom: 24px;
  padding: 16px;
  background: #f8f9fa;
  border-radius: 8px;
}

.user-info-section h4,
.config-section h4,
.camera-section h4,
.action-section h4,
.result-section h4 {
  margin: 0 0 16px 0;
  color: #303133;
  font-size: 16px;
  font-weight: 600;
}

.user-info-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  background: white;
  border-radius: 6px;
  border: 1px solid #e4e7ed;
}

.user-details {
  flex: 1;
}

.user-name {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
  font-weight: 500;
}

.user-id {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: #606266;
}

.camera-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.camera-preview {
  position: relative;
  width: 100%;
  max-width: 640px;
  background: #000;
  border-radius: 8px;
  overflow: hidden;
}

.camera-status {
  position: absolute;
  top: 10px;
  left: 10px;
  right: 10px;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  border-radius: 4px;
  font-size: 14px;
}

.camera-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #f56c6c;
}

.camera-status.active .camera-status-dot {
  background: #67c23a;
  animation: pulse 2s infinite;
}

@keyframes pulse {
  0% { opacity: 1; }
  50% { opacity: 0.5; }
  100% { opacity: 1; }
}

.camera-video {
  width: 100%;
  height: auto;
  display: block;
}

.camera-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  color: #909399;
  text-align: center;
}

.placeholder-tip {
  font-size: 12px;
  color: #c0c4cc;
  margin-top: 8px;
}

.captured-preview {
  position: relative;
  display: inline-block;
}

.captured-image {
  max-width: 100%;
  height: auto;
  border-radius: 6px;
}

.captured-overlay {
  position: absolute;
  top: 8px;
  right: 8px;
}

.camera-controls {
  display: flex;
  gap: 12px;
  justify-content: center;
}

.action-buttons {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.result-details {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.result-item {
  display: flex;
  align-items: center;
  gap: 6px;
}

.result-label {
  font-weight: 500;
  color: #606266;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}
</style>